import json
from pathlib import Path
import os
import aiohttp
from bs4 import BeautifulSoup
from functools import lru_cache
from .utils import strip_array_strings

async def get_random_anekdot():
  PAGE_URL = 'https://www.anekdot.ru/random/anekdot/'

  session = aiohttp.ClientSession()

  response = await session.get(PAGE_URL)
  page_content = await response.read()

  await session.close()

  soup = BeautifulSoup(page_content, 'html.parser')

  anekdot = soup.select_one('.text').getText(separator='\n')

  return anekdot

def make_anarchy_text(text: str):
  anarchy_text = ' '.join(list(text.upper()))

  return anarchy_text

async def get_synonyms(word: str):
  API_URL = 'https://synonymonline.ru/assets/json/synonyms.json'

  session = aiohttp.ClientSession()

  response = await session.post(
    API_URL,
    data={'word': word},
  )
  result = await response.json(content_type=None)

  await session.close()

  return strip_array_strings(result['synonyms'])

async def get_antonyms(word: str):
  API_URL = 'https://antonymonline.ru/antonyms.json'

  session = aiohttp.ClientSession()

  response = await session.post(
    API_URL,
    params=[('word', word)],
  )
  result = await response.json(content_type=None)

  await session.close()

  return {
    'typo': result.get('typo', []),
    'antonyms': strip_array_strings(result.get('antonyms', []))
  }

@lru_cache(maxsize=1)
def get_holidays():
  return json.loads(
    open(
      Path(
        os.path.join(os.getcwd(), './text/static_data/holidays.json')
      ),
      'r',
      encoding='utf8'
    ).read()
  )


def find_holidays(day: int, month: int):
  holidays = get_holidays()

  results = []

  for holiday in holidays:
    if day == holiday['day'] and month == holiday['month']:
      results.append(holiday)

  return results

async def online_compiler(language: str, file_ext: str, code: str):
  API_URL = 'https://onecompiler.com/api/code/exec'

  session = aiohttp.ClientSession()

  response = await session.post(
    API_URL,
    json={
      'properties': {
        'language': language,
        'files': [{
          'name': f'file.{file_ext}',
          'content': code,
        }]
      },
    }
  )

  result = await response.json()
  await session.close()

  return {
    'stderr': result['stderr'],
    'stdout': result['stdout'],
    'exec_time': result['time']
  }

def execute_code(language: str, code: str):
  language = language.lower()

  # Это нормально... Дураки не любят гениальных...
  code_executors = {
    'java': lambda: online_compiler(language, 'java', code),
    'c': lambda: online_compiler(language, 'c', code),
    'javascript': lambda: online_compiler(language, 'js', code),
    'groovy': lambda: online_compiler(language, 'groovy', code),
    'haskell': lambda: online_compiler(language, 'hs', code),
    'lua': lambda: online_compiler(language, 'js', code),
    'commonlisp': lambda: online_compiler(language, 'lsp', code),
    'elixir': lambda: online_compiler(language, 'ex', code),
    'fsharp': lambda: online_compiler(language, 'fs', code),
    'assembly': lambda: online_compiler(language, 'ex', code),
    'php': lambda: online_compiler(language, 'ex', code),
    'csharp': lambda: online_compiler(language, 'cs', code),
    'ruby': lambda: online_compiler(language, 'rb', code),
    'elixir': lambda: online_compiler(language, 'ex', code),
    'r': lambda: online_compiler(language, 'r', code),
    'ocaml': lambda: online_compiler(language, 'ml', code),
    'bash': lambda: online_compiler(language, 'sh', code),
    'typescript': lambda: online_compiler(language, 'ts', code),
    'kotlin': lambda: online_compiler(language, 'kt', code),
    'prolog': lambda: online_compiler(language, 'pl', code),
    'swift': lambda: online_compiler(language, 'swift', code),
    'python': lambda: online_compiler(language, 'py', code),
    'cpp': lambda: online_compiler(language, 'cpp', code),
    'tcl': lambda: online_compiler(language, 'tcl', code),
    'ada': lambda: online_compiler(language, 'adb', code),
    'erlang': lambda: online_compiler(language, 'erl', code),
    'fortran': lambda: online_compiler(language, 'ftn', code),
    'scala': lambda: online_compiler(language, 'scala', code),
    'perl': lambda: online_compiler(language, 'pl', code),
    'go': lambda: online_compiler(language, 'go', code),
    'racket': lambda: online_compiler(language, 'rkt', code),
    'visualbasic': lambda: online_compiler(language, 'vb', code),
    'clojure': lambda: online_compiler(language, 'clj', code),
    'cobol': lambda: online_compiler(language, 'cbl', code),
    'pascal': lambda: online_compiler(language, 'pas', code),
    'rust': lambda: online_compiler(language, 'rs', code),
    'octave': lambda: online_compiler(language, 'm', code),
  }

  code_executor = code_executors[language]

  if code_executor is None:
    return None

  return code_executor()
